package com.king.platform.utils.json;

import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.king.platform.exception.JacksonJsonException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.DefaultConversionService;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.List;
import java.util.Set;

public class MyJacksonUtils {
  private static final Logger log = LoggerFactory.getLogger(MyJacksonUtils.class);
  private static final ConversionService DEFAULT_CONVERSION_SERVICE = new DefaultConversionService();
  public static final String DEFAULT_EMPTY_JSON_OBJECT = "{}";
  public static final String DEFAULT_EMPTY_JSON_ARRAY = "[]";
  public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
  private static final ObjectMapper DEFAULT_OBJECT_MAPPER = createDefaultObjectMapper();

  public static <T> String object2Json(T object) {
    return object2Json(DEFAULT_OBJECT_MAPPER, object);
  }

  public static String object2Json(ObjectMapper objectMapper, Object object) {
    try {
      if (object != null) {
        return object instanceof String ? object.toString() : objectMapper.writeValueAsString(object);
      } else {
        return null;
      }
    } catch (JsonProcessingException var3) {
      log.error("The JacksonUtil toJsonString is error : \n", var3);
      throw new JacksonJsonException(var3);
    }
  }

  public static String object2JsonWithPretty(Object object) {
    try {
      ObjectMapper objectMapper = new ObjectMapper();
      return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(object);
    } catch (JsonProcessingException var2) {
      log.error("The JacksonUtil toJsonString is error : \n", var2);
      throw new RuntimeException();
    }
  }

  public static byte[] object2Bytes(Object object) {
    try {
      ObjectMapper objectMapper = new ObjectMapper();
      return objectMapper.writeValueAsBytes(object);
    } catch (JsonProcessingException var2) {
      log.error("The JacksonUtil toJsonBytes is error : \n", var2);
      throw new RuntimeException();
    }
  }

  public static <T> T json2Object(String json, Class<T> clazz) {
    return json2Object(DEFAULT_OBJECT_MAPPER, json, clazz);
  }

  public static <T> T json2Object(ObjectMapper objectMapper, String json, Class<T> clazz) {
    try {
      return !StrUtil.isEmpty(json) ? objectMapper.readValue(json, clazz) : null;
    } catch (Exception var4) {
      log.error("The JacksonUtil jons2Object is error, json str is {}, class name is {} \n", new Object[]{json, clazz.getName(), var4});
      throw new JacksonJsonException(var4);
    }
  }

  public static <T> T json2Object(String json, TypeReference<T> typeReference) {
    return json2Object(DEFAULT_OBJECT_MAPPER, json, typeReference);
  }

  public static <T> T json2Object(String json, Json2ObjectConverter<T> converter) {
    try {
      return !StrUtil.isEmpty(json) ? converter.convert(DEFAULT_OBJECT_MAPPER, DEFAULT_OBJECT_MAPPER.readTree(json)) : null;
    } catch (Exception var3) {
      throw new JacksonJsonException(var3);
    }
  }

  public static <T> T json2Object(ObjectMapper objectMapper, String json, TypeReference<T> typeReference) {
    try {
      return !StrUtil.isEmpty(json) ? objectMapper.readValue(json, typeReference) : null;
    } catch (Exception var4) {
      throw new JacksonJsonException(var4);
    }
  }

  public static String json2Str(Object obj) {
    if (null == obj) {
      return null;
    } else {
      return obj instanceof CharSequence ? StrUtil.str((CharSequence) obj) : json2Str(object2Json(obj));
    }
  }

  @SafeVarargs
  public static <T> List<T> parseList(String json, Class<T>... elementClasses) {
    try {
      ObjectMapper objectMapper = new ObjectMapper();
      return (List) objectMapper.readValue(json, getCollectionType(objectMapper, List.class, elementClasses));
    } catch (Exception var3) {
      log.error("The JacksonUtil parseList is error, json str is {}, element class name is {} \n", new Object[]{json, elementClasses.getClass().getName(), var3});
      throw new RuntimeException();
    }
  }

  @SafeVarargs
  public static <T> Set<T> parseSet(String json, Class<T>... elementClasses) {
    try {
      ObjectMapper objectMapper = new ObjectMapper();
      return (Set) objectMapper.readValue(json, getCollectionType(objectMapper, Set.class, elementClasses));
    } catch (Exception var3) {
      log.error("The JacksonUtil parseSet is error, json str is {}, element class name is {} \n", new Object[]{json, elementClasses.getClass().getName(), var3});
      throw new RuntimeException();
    }
  }

  @SafeVarargs
  public static <T> Collection<T> parseCollection(String json, Class<T>... elementClasses) {
    try {
      ObjectMapper objectMapper = new ObjectMapper();
      return (Collection) objectMapper.readValue(json, getCollectionType(objectMapper, Collection.class, elementClasses));
    } catch (Exception var3) {
      log.error("The JacksonUtil parseCollection is error, json str is {}, element class name is {} \n", new Object[]{json, elementClasses.getClass().getName(), var3});
      throw new RuntimeException();
    }
  }

  public static JavaType getCollectionType(ObjectMapper mapper, Class<?> collectionClass, Class<?>... elementClasses) {
    return mapper.getTypeFactory().constructParametricType(collectionClass, elementClasses);
  }

  public static ObjectMapper createDefaultObjectMapper() {
    ObjectMapper objectMapper = new CustomObjectMapper();
    objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
    objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
    objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
    objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
    objectMapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true);
    objectMapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
    objectMapper.registerModule(new Jdk8Module());
    objectMapper.registerModule(new JavaTimeModule());
    return objectMapper;
  }

  public static JsonNode createRootJsonNode(String json) {
    return createRootJsonNode(DEFAULT_OBJECT_MAPPER, json);
  }

  public static JsonNode createRootJsonNode(ObjectMapper objectMapper, String json) {
    try {
      return objectMapper.readTree(json);
    } catch (IOException var3) {
      throw new JacksonJsonException(var3.getMessage(), var3);
    }
  }

  public static boolean isJsonObject(String json) {
    if (json == null) {
      return false;
    } else {
      return json.startsWith("{") && json.endsWith("}");
    }
  }

  public static boolean isJsonArray(String json) {
    if (json == null) {
      return false;
    } else {
      return json.startsWith("[") && json.endsWith("]");
    }
  }

  public static boolean isJsonObjectArray(String json) {
    boolean b = isJsonArray(json);
    if (!b) {
      return false;
    } else {
      json = StringUtils.trim(StringUtils.strip(json, "[]"));
      return json.startsWith("{") && json.endsWith("}");
    }
  }

  public static String toString(JsonNode parentNode, String fieldName) {
    JsonNode jsonNode = parentNode.get(fieldName);
    return jsonNode != null ? jsonNode.toString() : null;
  }

  public static String getString(JsonNode parentNode, String fieldName) {
    return getString(parentNode, fieldName, (String) null);
  }

  public static String getString(JsonNode parentNode, String fieldName, String defaultValue) {
    JsonNode jsonNode = parentNode.get(fieldName);
    return jsonNode != null ? (String) StringUtils.defaultIfEmpty(jsonNode.asText(), defaultValue) : null;
  }

  public static Boolean getBoolean(JsonNode parentNode, String fieldName) {
    return getBoolean(parentNode, fieldName, (Byte) null);
  }

  public static Boolean getBoolean(JsonNode parentNode, String fieldName, Byte defaultValue) {
    String fieldValue = getString(parentNode, fieldName, defaultValue != null ? defaultValue.toString() : null);
    return fieldValue != null ? (Boolean) DEFAULT_CONVERSION_SERVICE.convert(fieldValue, Boolean.class) : null;
  }

  public static Byte getByte(JsonNode parentNode, String fieldName) {
    return getByte(parentNode, fieldName, (Byte) null);
  }

  public static Byte getByte(JsonNode parentNode, String fieldName, Byte defaultValue) {
    String fieldValue = getString(parentNode, fieldName, defaultValue != null ? defaultValue.toString() : null);
    return fieldValue != null ? (Byte) DEFAULT_CONVERSION_SERVICE.convert(fieldValue, Byte.class) : null;
  }

  public static Short getShort(JsonNode parentNode, String fieldName) {
    return getShort(parentNode, fieldName, (Short) null);
  }

  public static Short getShort(JsonNode parentNode, String fieldName, Short defaultValue) {
    String fieldValue = getString(parentNode, fieldName, defaultValue != null ? defaultValue.toString() : null);
    return fieldValue != null ? (Short) DEFAULT_CONVERSION_SERVICE.convert(fieldValue, Short.class) : null;
  }

  public static Integer getInteger(JsonNode parentNode, String fieldName) {
    return getInteger(parentNode, fieldName, (Integer) null);
  }

  public static Integer getInteger(JsonNode parentNode, String fieldName, Integer defaultValue) {
    String fieldValue = getString(parentNode, fieldName, defaultValue != null ? defaultValue.toString() : null);
    return fieldValue != null ? (Integer) DEFAULT_CONVERSION_SERVICE.convert(fieldValue, Integer.class) : null;
  }

  public static Float getFloat(JsonNode parentNode, String fieldName) {
    return getFloat(parentNode, fieldName, (Float) null);
  }

  public static Float getFloat(JsonNode parentNode, String fieldName, Float defaultValue) {
    String fieldValue = getString(parentNode, fieldName, defaultValue != null ? defaultValue.toString() : null);
    return fieldValue != null ? (Float) DEFAULT_CONVERSION_SERVICE.convert(fieldValue, Float.class) : null;
  }

  public static Double getDouble(JsonNode parentNode, String fieldName) {
    return getDouble(parentNode, fieldName, (Double) null);
  }

  public static Double getDouble(JsonNode parentNode, String fieldName, Double defaultValue) {
    String fieldValue = getString(parentNode, fieldName, defaultValue != null ? defaultValue.toString() : null);
    return fieldValue != null ? (Double) DEFAULT_CONVERSION_SERVICE.convert(fieldValue, Double.class) : null;
  }

  public static Long getLong(JsonNode parentNode, String fieldName) {
    return getLong(parentNode, fieldName, (Long) null);
  }

  public static Long getLong(JsonNode parentNode, String fieldName, Long defaultValue) {
    String fieldValue = getString(parentNode, fieldName, defaultValue != null ? defaultValue.toString() : null);
    return fieldValue != null ? (Long) DEFAULT_CONVERSION_SERVICE.convert(fieldValue, Long.class) : null;
  }

  public static ObjectMapper getDefaultObjectMapper() {
    return DEFAULT_OBJECT_MAPPER;
  }

  @FunctionalInterface
  public interface Json2ObjectConverter<T> {
    T convert(ObjectMapper objectMapper, JsonNode rootNode) throws Exception;
  }
}
